package com.zhongkai.tools;

import java.awt.image.AreaAveragingScaleFilter;
import java.awt.image.BufferedImage;
import java.awt.image.ColorModel;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageConsumer;
import java.awt.image.ImageProducer;
import java.awt.image.WritableRaster;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.imageio.IIOImage;
import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.ImageWriteParam;
import javax.imageio.ImageWriter;
import javax.imageio.plugins.jpeg.JPEGImageWriteParam;
import javax.imageio.stream.FileImageOutputStream;
import javax.imageio.stream.ImageInputStream;

import org.apache.log4j.Logger;
import org.apache.struts.upload.FormFile;

public class ImageScaler {

	public static void saveImage(String srcPath, String destPath, int destW,
			int destH) throws IOException {
		Logger log = Logger.getLogger("ImageScaler");
		BufferedImage srcImage = null;
		ImageWriter writer = null;
		BufferedImage destImage = null;
		FileImageOutputStream fos = null;
		try{
		File srcFilePath = new File(srcPath);
		File destFilePath = new File(destPath);
		File parent_path = new File(destFilePath.getParent());
		if (!parent_path.exists()) {
			parent_path.mkdirs();
		}
		long start = System.currentTimeMillis();
		srcImage = ImageIO.read(srcFilePath); //读取源图
		if (srcImage == null)
			log.info("不支持的图片格式，无法读取");

		int srcW = srcImage.getWidth(); //获取源图宽度
		int srcH = srcImage.getHeight(); //获取源图高度
		float factorX = (float) srcW / destW; //得到高的缩小比例800*600->400*300,则为2
		float factorY = (float) srcH / destH; //得到宽的缩小比例
		factorX = Math.max(factorX, factorY);
		if (factorX < 1) //如果最大的压缩比<1，说明高、宽都大于原始图像，则取1，即不变
			factorX = 1;
		factorY = factorX; //要等比压缩，高的压缩比永远跟宽保持一致
		AreaAveragingScaleFilter scaleFilter = new AreaAveragingScaleFilter(
				Math.round(srcW / factorX), Math.round(srcH / factorY)); //获得比例过滤器
		ImageProducer producer = new FilteredImageSource(srcImage.getSource(),
				scaleFilter); //将源图转为生产者
		ImageGenerator generator = new ImageGenerator(); //得到辅助类
		producer.startProduction(generator);
		destImage = generator.getImage(); //根据辅助信息生成目标类

		JPEGImageWriteParam param = new JPEGImageWriteParam(null); //得到图像生成工具,采用JPEG压缩标准
		param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); //设置压缩算法
		param.setCompressionQuality(1f); //设置图像质量为最高
		
		java.util.Iterator it = ImageIO.getImageWritersBySuffix("jpg"); //可以用JPG进行编码
		writer = (ImageWriter) it.next();
		fos = new FileImageOutputStream(destFilePath);
		writer.setOutput(fos); //设置输出对象
		writer.write(null, new IIOImage(destImage, null, null), param); //输出
		writer.dispose();
		
		
		long end = System.currentTimeMillis();
		log.info("----------生成小图完成，从读图到出图共用" + (end - start) + "ms");
		}finally{
			fos.close();
			destImage.flush();
			srcImage.flush();
			writer.dispose();
		}
	}
	
	public static boolean isImage(InputStream is) throws IOException {// 检查是否是图片
		boolean result = true;
		ImageInputStream iis = ImageIO.createImageInputStream(is);
		Iterator iter = ImageIO.getImageReaders(iis);
		if (!iter.hasNext())
			result = false;
		else {
			ImageReader reader = (ImageReader) iter.next();
			String formatter = reader.getFormatName();
			formatter = formatter.toLowerCase();
			if (!formatter.equals("jpeg") && !formatter.equals("bmp") && !formatter.equals("wbmp") && !formatter.equals("gif") && !formatter.equals("png"))
				result = false;
			iis.close();// 关闭图片输入流
			is.close();
		}
		return result;
	}
	
	public static void saveImage2(FormFile form, String destPath, int destW,
			int destH) throws Exception {
		Logger log = Logger.getLogger("ImageScaler");
		if(!isImage(form.getInputStream()))throw new Exception("图片格式验证出错，只能上传jpg，bmp，gif，png，wbmp格式的图片！");
		Pattern p = Pattern.compile(".html|.jsp|.exe|.bat");
		Matcher m = p.matcher(form.getFileName());
		if (m.matches()) {
			throw new RuntimeException("非法的文件名!");
		}
		if (form.getFileSize() > 5 * 1024 * 1024) {
			throw new RuntimeException("不支持5M以上的文件上传!");
		}
		BufferedImage srcImage = null;
		ImageWriter writer = null;
		BufferedImage destImage = null;
		FileImageOutputStream fos = null;
		try{
			File f = new File(destPath.substring(0,destPath.lastIndexOf(File.separator)));
			if(!f.exists())f.mkdirs();
		File destFilePath = new File(destPath);
		long start = System.currentTimeMillis();
		srcImage = ImageIO.read(form.getInputStream()); //读取源图
		if (srcImage == null)
			log.info("不支持的图片格式，无法读取");

		int srcW = srcImage.getWidth(); //获取源图宽度
		int srcH = srcImage.getHeight(); //获取源图高度
		float factorX = (float) srcW / destW; //得到高的缩小比例800*600->400*300,则为2
		float factorY = (float) srcH / destH; //得到宽的缩小比例
		factorX = Math.max(factorX, factorY);
		if (factorX < 1) //如果最大的压缩比<1，说明高、宽都大于原始图像，则取1，即不变
			factorX = 1;
		factorY = factorX; //要等比压缩，高的压缩比永远跟宽保持一致
		AreaAveragingScaleFilter scaleFilter = new AreaAveragingScaleFilter(
				Math.round(srcW / factorX), Math.round(srcH / factorY)); //获得比例过滤器
		ImageProducer producer = new FilteredImageSource(srcImage.getSource(),
				scaleFilter); //将源图转为生产者
		ImageGenerator generator = new ImageGenerator(); //得到辅助类
		producer.startProduction(generator);
		destImage = generator.getImage(); //根据辅助信息生成目标类

		JPEGImageWriteParam param = new JPEGImageWriteParam(null); //得到图像生成工具,采用JPEG压缩标准
		param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); //设置压缩算法
		param.setCompressionQuality(1f); //设置图像质量为最高
		
		java.util.Iterator it = ImageIO.getImageWritersBySuffix("jpg"); //可以用JPG进行编码
		writer = (ImageWriter) it.next();
		fos = new FileImageOutputStream(destFilePath);
		writer.setOutput(fos); //设置输出对象
		writer.write(null, new IIOImage(destImage, null, null), param); //输出
		writer.dispose();
		long end = System.currentTimeMillis();
		log.info("----------生成小图完成，从读图到出图共用" + (end - start) + "ms");
		}finally{
			fos.close();
			destImage.flush();
			srcImage.flush();
			writer.dispose();
		}
	}

}

//------------------------输助类-----------------------------------
class ImageGenerator implements ImageConsumer {
	private Object holder;
	private ColorModel colorModel;
	private Hashtable properties;
	private WritableRaster raster;
	private int width;
	private int height;
	private BufferedImage image;
	private int[] intBuffer;
	private boolean loadComplete;

	//构造器，定义辅助属性的初始值
	public ImageGenerator() {
		holder = new Object();
		width = -1;
		height = -1;
		loadComplete = false;
	}

	//完成时调用的方法
	public void imageComplete(int status) {
		// Logger log=Logger.getLogger("ImageGenerator");
		synchronized (holder) {
			loadComplete = true;
			holder.notify();
			//log.info("--------加载大图完成!-------------");
		}
	}

	//根据源图的色彩模式来设置新图
	public void setColorModel(ColorModel model) {
		colorModel = model;
		createImage();
	}

	//设置目标图片的宽、高
	public void setDimensions(int w, int h) {
		width = w;
		height = h;
		createImage();
	}

	public void setHints(int flags) {
	}

	//将尺寸分解为像素点，根据像素点来填充颜色,byte[]数组作为像素参数
	public void setPixels(int x, int y, int w, int h, ColorModel model,
			byte[] pixels, int offset, int scansize) {
		if ((intBuffer == null) || (pixels.length > intBuffer.length))
			intBuffer = new int[pixels.length];

		for (int i = pixels.length; --i >= 0;)
			intBuffer[i] = pixels[i] & 0xFF;

		raster.setPixels(x, y, w, h, intBuffer);
	}

	//将尺寸分解为像素点，根据像素点来填充颜色,int[]数组作为像素参数
	public void setPixels(int x, int y, int w, int h, ColorModel model,
			int[] pixels, int offset, int scansize) {
		image.setRGB(x, y, w, h, pixels, offset, scansize);
	}

	//设置图片属性
	public void setProperties(Hashtable props) {
		this.properties = props;
		createImage();
	}

	//返回创建的新图片
	public BufferedImage getImage() {
		if (!loadComplete) {
			synchronized (holder) {
				try {
					holder.wait();
				} catch (InterruptedException ie) {
				}
			}
		}

		return image;
	}

	//创建图片
	private void createImage() {
		if ((image != null) || (width == -1) || (colorModel == null))
			return;
		image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
	}
	
	
	
}
